package br.com.beyondclick.model.entity;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.com.gentech.commons.model.entity.IdentifiableEntity;

/**
 * @author AC de Souza
 */
@Entity
public class Compra implements IdentifiableEntity<Long> {
	private static final long serialVersionUID = 1L;

	@Id @GeneratedValue
	private Long id;
	@Temporal(TemporalType.DATE)
	private Date data;
	@ManyToOne(optional=false)
	private Cheque cheque;
	private String fornecedor;
	private String notaFiscal;
	
	@OneToMany(mappedBy="compra", cascade=CascadeType.ALL)
	private List<CompraMaterial> compraMateriais;

	public Compra(){
		data = new Date();
	}

	public void addCompraMaterial(CompraMaterial compraMaterial){
		if( compraMateriais == null ) compraMateriais = new ArrayList<CompraMaterial>();

		compraMaterial.setCompra(this);
		compraMateriais.add(compraMaterial);
	}

	public void atenderPedidosPendentes( List<PedidoMaterial> pedidosMateriaisPendentes ){
		for ( CompraMaterial compraMaterial : this.getCompraMateriais() ){
			compraMaterial.atender( pedidosMateriaisPendentes );
		}
	}

	/**
	 * Calcular o total, em dinheiro, desta {@link Compra}.
	 * 
	 * @return Valor total desta {@link Compra}.
	 */
	public BigDecimal getTotalCusto(){
		BigDecimal totalCompras = new BigDecimal(BigInteger.ZERO, 2);
		BigDecimal totalParcial = new BigDecimal(BigInteger.ZERO, 2);
		for (CompraMaterial compraMaterial : this.getCompraMateriais()) {
			totalParcial = compraMaterial.getPreco().multiply( BigDecimal.valueOf(compraMaterial.getQuantidade()) );
			totalCompras = totalCompras.add( totalParcial );
		}

		return totalCompras;
	}

	/**
	 * Remove todos os itens que a quantidade for menor ou igual a 0(zero).
	 * 
	 * @param materiaisPedidos the materiaisPedidos to set
	 */
	public void setCompraMateriais(List<CompraMaterial> materiaisPedidos) {
		for (CompraMaterial compraMaterial : materiaisPedidos) {
	        if( compraMaterial.getQuantidade() <= 0 )
	        	materiaisPedidos.remove(compraMaterial);
			else
				compraMaterial.setCompra(this);
        }
		this.compraMateriais = materiaisPedidos;
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + (int) (id ^ (id >>> 32));
		return result;
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Compra other = (Compra) obj;
		if (id != other.id)
			return false;
		return true;
	}

	/**
	 * O m�todo da interface foi renomeado para resolver um problema do Stripes.
	 * O problema consiste na incapacidade de recuperar o m�todo modificador do atributo id:
	 * http://stripes.mc4j.org/jira/browse/STS-285
	 * 
	 * @return the id
	 */
	public Long getOID() {
		return getId();
	}
	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return the fornecedor
	 */
	public String getFornecedor() {
		return fornecedor;
	}

	/**
	 * @param fornecedor the fornecedor to set
	 */
	public void setFornecedor(String fornecedor) {
		this.fornecedor = fornecedor;
	}

	/**
	 * @return the materiaisPedidos
	 */
	public List<CompraMaterial> getCompraMateriais() {
		return compraMateriais;
	}

	/**
	 * @return the notaFiscal
	 */
	public String getNotaFiscal() {
		return notaFiscal;
	}

	/**
	 * @param notaFiscal the notaFiscal to set
	 */
	public void setNotaFiscal(String notaFiscal) {
		this.notaFiscal = notaFiscal;
	}

	/**
	 * @return the cheque
	 */
	public Cheque getCheque() {
		return cheque;
	}

	/**
	 * @param cheque the cheque to set
	 */
	public void setCheque(Cheque cheque) {
		this.cheque = cheque;
	}
	/**
	 * @return the data
	 */
	public Date getData() {
		if(data == null)
			data = new Date();

		return data;
	}
	/**
	 * @param data the data to set
	 */
	public void setData(Date data) {
		this.data = data;
	}
}